package mvc.core.impl;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import com.google.inject.Guice;
import com.google.inject.Injector;

import mvc.core.IMachuPicchu;
import mvc.effects.IEffect;
import mvc.effects.impl.EffectsHandler;
import mvc.exporter.impl.ExportHandler;
import mvc.imageProcessor.impl.ImageProcessor;
import mvc.importer.impl.ImportHandler;
import mvc.library.impl.LibraryHandler;
import mvc.utils.FileUtilitys;

public class MachuPicchu implements IMachuPicchu {
	private Injector injector;
	private ImportHandler importHandler;
	private ExportHandler exportHandler;
	private ImageProcessor imageProcessor;
	private String uniqueRuntimePath;
	private EffectsHandler effectsHandler;
	private LibraryHandler libraryHandler;
	private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

	private MachuPicchu() {
		injector = Guice.createInjector(new MPModule());
		importHandler = injector.getInstance(ImportHandler.class);
		exportHandler = injector.getInstance(ExportHandler.class);
		libraryHandler = injector.getInstance(LibraryHandler.class);
		effectsHandler = new EffectsHandler();// injector.getInstance(EffectsHandler.class);
		imageProcessor = new ImageProcessor();
		uniqueRuntimePath = "MachuPicchu_" + System.currentTimeMillis()
				+ File.separator;

	}

	private static class MachuPicchuHolder {
		private static final MachuPicchu INSTANCE = new MachuPicchu();
	}

	public static MachuPicchu getInstance() {
		return MachuPicchuHolder.INSTANCE;
	}

	@Override
	public void exportImages() {
		try {
			exportHandler.exportImages(libraryHandler.getSelectedImages());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		pcs.firePropertyChange("imageListChanged", "Bla", "hej");
	}

	@Override
	public List<MachuImage> getImageList() {
		return libraryHandler.getImages();
	}

	@Override
	public void importImages() {
		try {

			List<MachuImage> importedImages = importHandler.getImages();
			libraryHandler.addImages(importedImages);
			libraryHandler.setSelectedImages(importedImages);
			pcs.firePropertyChange("imageListChanged", "bla", "hej");
		} catch (IOException e) { // TODO
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public void addPropertyChangeListener(PropertyChangeListener l) {
		pcs.addPropertyChangeListener(l);

	}

	@Override
	public void removePropertyChangeListener(PropertyChangeListener l) {
		pcs.removePropertyChangeListener(l);

	}

	@Override
	public void removeImage(List<MachuImage> list) {
		libraryHandler.removeImages(list);
		pcs.firePropertyChange("imageListChanged", "Blo", "haje");
	}

	@Override
	public String getUniqueRuntimePath() {
		return uniqueRuntimePath;
	}

	@Override
	public ImageProcessor getImageProcessor() {
		return imageProcessor;
	}

	@Override
	public List<MachuImage> getSelectedImages() {
		return libraryHandler.getSelectedImages();
	}

	@Override
	public void setSelectedImages(List<MachuImage> list) {
		libraryHandler.setSelectedImages(list);
		pcs.firePropertyChange("selectedImagesChanged", "bla", "hej");

	}

	@Override
	public void applyEffect(IEffect effect) {

		List<MachuImage> selectedImages = libraryHandler.getSelectedImages();
		for (MachuImage mi : selectedImages) {
			mi.getEffectsList().add(effect);
		}
		imageProcessor.processThumbnailImages(selectedImages);

		// List<BufferedImage> temporaryList =
		// imageProcessor.processImage(selectedImages);
		// libraryHandler.setSelectedImages(temporaryList);

		// TODO Make it possible to apply the effect to the image currently on
		// the centerstage
		// this.getCenterStageImage.
		pcs.firePropertyChange("imageListChanged", "Blo", "haje");
	}

	@Override
	public List<IEffect> getListWithEffects() {

		return effectsHandler.getListWithEffects();
	}

	/**
	 * Performs a controlled shutdown of the application.
	 */
	@Override
	public void shutdown(){

		FileUtilitys.removeFileDirectory(this.getUniqueRuntimePath());
	}

	@Override
	public Image getScaledImage(Image img, int i, int t) throws IOException {

		return imageProcessor.createScaledImage(img, i, t);

	}

}
